package com.crowntit.infrastructure.adapter.repository;

import com.alibaba.fastjson.JSON;
import com.crowntit.domain.activity.adapter.repository.IActivityRepository;
import com.crowntit.domain.activity.model.entity.IndexTeamQueryEntity;
import com.crowntit.domain.activity.model.entity.UserGroupBuyTeamDetailEntity;
import com.crowntit.domain.activity.model.entity.ScSkuEntity;
import com.crowntit.domain.activity.model.entity.SkuActivityEntity;
import com.crowntit.domain.activity.model.valobj.DiscountTypeEnum;
import com.crowntit.domain.activity.model.valobj.GroupBuyActivityDiscountVO;
import com.crowntit.domain.activity.model.valobj.SkuVO;
import com.crowntit.infrastructure.DCCService;
import com.crowntit.infrastructure.dao.*;
import com.crowntit.infrastructure.dao.po.*;
import com.crowntit.infrastructure.redis.IRedisService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RBitSet;
import org.springframework.stereotype.Repository;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Repository
@Slf4j
public class ActivityRepository extends AbstractRepository implements IActivityRepository {

    @Resource
    private IGroupBuyActivityDao groupBuyActivityDao;
    @Resource
    private IGroupBuyDiscountDao groupBuyDiscountDao;
    @Resource
    private IScSkuActivityDao scSkuActivityDao;
    @Resource
    private IGroupBuyOrderDao groupBuyOrderDao;
    @Resource
    private IGroupBuyOrderListDao groupBuyOrderListDao;
    @Resource
    private ISkuDao skuDao;
    @Resource
    private ICrowdTagsDetailDao crowdTagsDetailDao;
    @Resource
    private IRedisService redisService;
    @Resource
    private DCCService dccService;

    @Override
    public GroupBuyActivityDiscountVO queryGroupBuyActivityDiscountVO(Long activityId, String source, String channel) {
        ScSkuActivity scSkuActivityReq, scSkuActivity;
        if (activityId == null){
            scSkuActivityReq = ScSkuActivity.builder()
                    .source(source)
                    .channel(channel)
                    .build();
            scSkuActivity = scSkuActivityDao.queryActivityBySc(scSkuActivityReq);
        } else {
            scSkuActivityReq = ScSkuActivity.builder()
                    .activityId(activityId)
                    .build();
            scSkuActivity = scSkuActivityDao.queryActivityByActivityId(scSkuActivityReq);
        }

//        GroupBuyActivity groupBuyActivity = groupBuyActivityDao.queryValidGroupBuyActivityByActivityId(scSkuActivity.getActivityId());
        GroupBuyActivity groupBuyActivity = getFromCacheOrDb(GroupBuyActivity.cacheRedisKey(activityId), () -> groupBuyActivityDao.queryValidGroupBuyActivityByActivityId(activityId));
        if (groupBuyActivity == null)
            return null;

        GroupBuyDiscount groupBuyDiscount = groupBuyDiscountDao.queryGroupBuyDiscountByDiscountId(groupBuyActivity.getDiscountId());

        GroupBuyActivityDiscountVO.GroupBuyDiscount activityGroupBuyDiscount = GroupBuyActivityDiscountVO.GroupBuyDiscount.builder()
                .discountDesc(groupBuyDiscount.getDiscountDesc())
                .discountName(groupBuyDiscount.getDiscountName())
                .discountType(DiscountTypeEnum.get(Byte.toUnsignedInt(groupBuyDiscount.getDiscountType())))
                .tagId(groupBuyDiscount.getTagId())
                .marketExpr(groupBuyDiscount.getMarketExpr())
                .marketPlan(groupBuyDiscount.getMarketPlan())
                .build();

        GroupBuyActivityDiscountVO groupBuyActivityDiscountVO = GroupBuyActivityDiscountVO.builder()
                .activityId(groupBuyActivity.getActivityId())
                .activityName(groupBuyActivity.getActivityName())
                .source(scSkuActivity.getSource())
                .channel(scSkuActivity.getChannel())
                .goodsId(scSkuActivity.getGoodsId())
                .groupBuyDiscount(activityGroupBuyDiscount)
                .groupType(groupBuyActivity.getGroupType())
                .takeLimitCount(groupBuyActivity.getTakeLimitCount())
                .startTime(groupBuyActivity.getStartTime())
                .endTime(groupBuyActivity.getEndTime())
                .validTime(groupBuyActivity.getValidTime())
                .target(groupBuyActivity.getTarget())
                .status(groupBuyActivity.getStatus())
                .tagId(groupBuyActivity.getTagId())
                .tagScope(groupBuyActivity.getTagScope())
                .build();

        return groupBuyActivityDiscountVO;
    }

    @Override
    public SkuVO querySkuByScGoodsId(ScSkuEntity scSkuEntity) {
        String source = scSkuEntity.getSource();
        String channel = scSkuEntity.getChannel();
        String goodsId = scSkuEntity.getGoodsId();

        Sku sku = skuDao.querySkuByScGoodsId(Sku.builder()
                .goodsId(goodsId)
                .source(source)
                .channel(channel)
                .build());
        if (sku == null)
            return null;

        return SkuVO.builder()
                .goodsId(sku.getGoodsId())
                .goodsName(sku.getGoodsName())
                .originalPrice(sku.getOriginalPrice())
                .build();
    }

    @Override
    public boolean isCrowdRange(String userId, String tagId) {
        RBitSet bitSet = redisService.getBitSet(tagId);
        int index = redisService.getIndexFromUserId(userId);
        boolean isCrowdRangeRedis = bitSet.get(index);
        if (isCrowdRangeRedis){
            return true;
        }

        CrowdTagsDetail crowdTagsDetail = crowdTagsDetailDao.queryCrowdTagsDetail(CrowdTagsDetail.builder()
                .userId(userId)
                .tagId(tagId)
                .build());
        if (crowdTagsDetail != null){
            return true;
        }
        return false;
    }

    @Override
    public boolean isDegrade() {
        return dccService.isDegrade();
    }

    @Override
    public boolean isCutRange(String userId) {
        return dccService.isCutRange(userId);
    }

    @Override
    public SkuActivityEntity querySkuConfig(ScSkuEntity scSkuEntity) {
        String source = scSkuEntity.getSource();
        String channel = scSkuEntity.getChannel();
        String goodsId = scSkuEntity.getGoodsId();

        Sku skuRes = skuDao.querySku(Sku.builder()
                .channel(channel)
                .source(source)
                .goodsId(goodsId)
                .build());
        if (skuRes == null) return null;

        ScSkuActivity scSkuActivity = scSkuActivityDao.queryActivity(ScSkuActivity.builder()
                .source(source)
                .channel(channel)
                .goodsId(goodsId)
                .build());

        if (scSkuActivity.getActivityId() != null && scSkuActivity.getActivityId() != 0) {
//            GroupBuyActivity groupBuyActivity = groupBuyActivityDao.queryValidGroupBuyActivityByActivityId(scSkuActivity.getActivityId());
            Long activityId = scSkuActivity.getActivityId();
            GroupBuyActivity groupBuyActivity = getFromCacheOrDb(GroupBuyActivity.cacheRedisKey(activityId), () -> groupBuyActivityDao.queryValidGroupBuyActivityByActivityId(activityId));
            if (groupBuyActivity == null) {
                scSkuActivity.setActivityId(null);
            }
        }

        return SkuActivityEntity.builder()
                .goodsName(skuRes.getGoodsName())
                .goodsId(goodsId)
                .source(source)
                .channel(channel)
                .originalPrice(skuRes.getOriginalPrice())
                .activityId(scSkuActivity.getActivityId())
                .build();
    }

    @Override
    public UserGroupBuyTeamDetailEntity queryGroupBuyTeamDetailByUser(IndexTeamQueryEntity queryEntity) {
        String source = queryEntity.getSource();
        String channel = queryEntity.getChannel();
        String goodsId = queryEntity.getGoodsId();
        Long activityId = queryEntity.getActivityId();
        String userId = queryEntity.getUserId();

        GroupBuyOrderList groupBuyOrderList = groupBuyOrderListDao.queryOrderListByUser(GroupBuyOrderList.builder()
                .userId(userId)
                .activityId(activityId)
                .source(source)
                .channel(channel)
                .goodsId(goodsId)
                .build());
        if (groupBuyOrderList == null) return null;

        GroupBuyOrder groupBuyOrder = groupBuyOrderDao.queryValidGroupBuyOrderByTeamId(groupBuyOrderList.getTeamId());
        if (groupBuyOrder == null) return null;

        return UserGroupBuyTeamDetailEntity.builder()
                .source(source)
                .channel(channel)
                .teamId(groupBuyOrder.getTeamId())
                .userId(userId)
                .activityId(activityId)
                .outTradeNo(groupBuyOrderList.getOutTradeNo())
                .targetCount(groupBuyOrder.getTargetCount())
                .completeCount(groupBuyOrder.getCompleteCount())
                .lockCount(groupBuyOrder.getLockCount())
                .validStartTime(groupBuyOrder.getValidStartTime())
                .validEndTime(groupBuyOrder.getValidEndTime())
                .build();
    }

    @Override
    public List<UserGroupBuyTeamDetailEntity> queryIndexTeamList(IndexTeamQueryEntity queryEntity) {
        String source = queryEntity.getSource();
        String channel = queryEntity.getChannel();
        String goodsId = queryEntity.getGoodsId();
        Long activityId = queryEntity.getActivityId();

        // 找同商品活动下的拼团组队
        List<GroupBuyOrderList> scActivityOrderLists = groupBuyOrderListDao.queryIndexOrderListByScActivity(GroupBuyOrderList.builder()
                .activityId(activityId)
                .source(source)
                .channel(channel)
                .goodsId(goodsId)
                .build());
        log.info("目标商品-团购活动的拼团组队orderLists: {}", JSON.toJSONString(scActivityOrderLists));
        if (scActivityOrderLists == null || scActivityOrderLists.isEmpty()) return null;

        // 过滤TeamId
        Set<String> teamIdSet = new HashSet<>();
        teamIdSet.addAll(scActivityOrderLists.stream()
                .map(GroupBuyOrderList::getTeamId)
                .filter(teamId -> teamId != null && !teamId.isEmpty())
                .collect(Collectors.toSet()));

        if (StringUtils.isNotBlank(queryEntity.getTeamIdUserIn())){
            teamIdSet.remove(queryEntity.getTeamIdUserIn());
        }
        log.info("orderLists过滤后的teamIdSet: {}", JSON.toJSONString(teamIdSet));

        // 查teamId对应的order组队信息
        if (teamIdSet.isEmpty()) return null;

        List<GroupBuyOrder> groupBuyOrders = groupBuyOrderDao.queryTeamProgressInTeamIds(teamIdSet);
        log.info("teamIdSet查到的teamProgress信息: {}", JSON.toJSONString(groupBuyOrders));
        if (null == groupBuyOrders || groupBuyOrders.isEmpty()) return null;

        Map<String, GroupBuyOrder> groupBuyOrderMap = groupBuyOrders.stream()
                .collect(Collectors.toMap(GroupBuyOrder::getTeamId, order -> order));

        List<UserGroupBuyTeamDetailEntity> teamList = new ArrayList<>();
        for (GroupBuyOrderList scActivityOrderList : scActivityOrderLists) {
            String teamId = scActivityOrderList.getTeamId();
            GroupBuyOrder groupBuyOrder = groupBuyOrderMap.get(teamId);
            if (null == groupBuyOrder) continue;

            UserGroupBuyTeamDetailEntity userGroupBuyOrderDetailEntity = UserGroupBuyTeamDetailEntity.builder()
                    .userId(scActivityOrderList.getUserId())
                    .teamId(groupBuyOrder.getTeamId())
                    .activityId(groupBuyOrder.getActivityId())
                    .targetCount(groupBuyOrder.getTargetCount())
                    .completeCount(groupBuyOrder.getCompleteCount())
                    .lockCount(groupBuyOrder.getLockCount())
                    .validStartTime(groupBuyOrder.getValidStartTime())
                    .validEndTime(groupBuyOrder.getValidEndTime())
                    .build();

            teamList.add(userGroupBuyOrderDetailEntity);
        }
        return teamList;
    }
}
